package com.zx1316.javasimpledoudizhu.client.ui;

import com.zx1316.javasimpledoudizhu.DDZApplication;
import com.zx1316.javasimpledoudizhu.Main;
import com.zx1316.javasimpledoudizhu.client.Judge;
import com.zx1316.javasimpledoudizhu.client.ReceiveThread;
import com.zx1316.javasimpledoudizhu.misc.Card;
import com.zx1316.javasimpledoudizhu.server.ui.ServerController;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Vector;

public class ClientController {
    private final MediaPlayer mediaPlayer = new MediaPlayer(new Media(Main.class.getResource("bgm.mp3").toString()));
    public Label rounds;
    public Label landlordCard;
    public Label points;
    public Label name3;
    public Label remaining3;
    public Label score3;
    public Label landlord3;
    public Label double3;
    public Label offline3;
    public Label remaining2;
    public Label name2;
    public Label score2;
    public Label double2;
    public Label landlord2;
    public Label offline2;
    public Label name1;
    public Label remaining1;
    public Label score1;
    public Label landlord1;
    public Label double1;
    public Label oJB;
    public Label oJS;
    public Label o2;
    public Label o3;
    public Label o4;
    public Label o5;
    public Label o6;
    public Label o7;
    public Label o8;
    public Label o9;
    public Label o10;
    public Label oJ;
    public Label oQ;
    public Label oK;
    public Label oA;
    public Button call1;
    public Button call2;
    public Button call3;
    public Button pass;
    public Button confirm;
    public Label info3;
    public Label info1;
    public Label info2;
    public ImageView card1;
    public ImageView card2;
    public ImageView card3;
    public ImageView card4;
    public ImageView card5;
    public ImageView card6;
    public ImageView card7;
    public ImageView card8;
    public ImageView card9;
    public ImageView card10;
    public ImageView card11;
    public ImageView card12;
    public ImageView card13;
    public ImageView card14;
    public ImageView card15;
    public ImageView card16;
    public ImageView card17;
    public ImageView card18;
    public ImageView card19;
    public ImageView card20;
    public ImageView p1Discard1;
    public ImageView p1Discard2;
    public ImageView p1Discard3;
    public ImageView p1Discard4;
    public ImageView p1Discard5;
    public ImageView p1Discard6;
    public ImageView p1Discard7;
    public ImageView p1Discard8;
    public ImageView p1Discard9;
    public ImageView p1Discard10;
    public ImageView p1Discard11;
    public ImageView p1Discard12;
    public ImageView p1Discard13;
    public ImageView p1Discard14;
    public ImageView p1Discard15;
    public ImageView p1Discard16;
    public ImageView p1Discard17;
    public ImageView p1Discard18;
    public ImageView p1Discard19;
    public ImageView p1Discard20;
    public ImageView p3Discard1;
    public ImageView p3Discard2;
    public ImageView p3Discard3;
    public ImageView p3Discard4;
    public ImageView p3Discard5;
    public ImageView p3Discard6;
    public ImageView p3Discard7;
    public ImageView p3Discard8;
    public ImageView p3Discard9;
    public ImageView p3Discard10;
    public ImageView p3Discard11;
    public ImageView p3Discard12;
    public ImageView p3Discard13;
    public ImageView p3Discard14;
    public ImageView p3Discard15;
    public ImageView p3Discard16;
    public ImageView p3Discard17;
    public ImageView p3Discard18;
    public ImageView p3Discard19;
    public ImageView p3Discard20;
    public ImageView p2Discard10;
    public ImageView p2Discard9;
    public ImageView p2Discard8;
    public ImageView p2Discard7;
    public ImageView p2Discard6;
    public ImageView p2Discard5;
    public ImageView p2Discard4;
    public ImageView p2Discard3;
    public ImageView p2Discard2;
    public ImageView p2Discard1;
    public ImageView p2Discard20;
    public ImageView p2Discard19;
    public ImageView p2Discard18;
    public ImageView p2Discard17;
    public ImageView p2Discard16;
    public ImageView p2Discard15;
    public ImageView p2Discard14;
    public ImageView p2Discard13;
    public ImageView p2Discard12;
    public ImageView p2Discard11;
    public TextField hostname;
    public TextField port;
    public PasswordField pwd;
    public TextField name;
    public Button connect;
    public Button disconnect;
    public Button openServer;
    public TextArea chatHistory;
    public TextArea chat;
    public Button send;
    public GridPane tips;
    private boolean[] selectedCards = new boolean[20];
    private ReceiveThread receiveThread;
    private Socket socket;
    private PrintWriter writer;
    private Judge judge;

    public void card1Clicked() {
        if (selectedCards[0]) {
            card1.setY(0);
        } else {
            card1.setY(-20);
        }
        selectedCards[0] = !selectedCards[0];
    }

    public void card2Clicked() {
        if (selectedCards[1]) {
            card2.setY(0);
        } else {
            card2.setY(-20);
        }
        selectedCards[1] = !selectedCards[1];
    }

    public void card3Clicked() {
        if (selectedCards[2]) {
            card3.setY(0);
        } else {
            card3.setY(-20);
        }
        selectedCards[2] = !selectedCards[2];
    }

    public void card4Clicked() {
        if (selectedCards[3]) {
            card4.setY(0);
        } else {
            card4.setY(-20);
        }
        selectedCards[3] = !selectedCards[3];
    }

    public void card5Clicked() {
        if (selectedCards[4]) {
            card5.setY(0);
        } else {
            card5.setY(-20);
        }
        selectedCards[4] = !selectedCards[4];
    }

    public void card6Clicked() {
        if (selectedCards[5]) {
            card6.setY(0);
        } else {
            card6.setY(-20);
        }
        selectedCards[5] = !selectedCards[5];
    }

    public void card7Clicked() {
        if (selectedCards[6]) {
            card7.setY(0);
        } else {
            card7.setY(-20);
        }
        selectedCards[6] = !selectedCards[6];
    }

    public void card8Clicked() {
        if (selectedCards[7]) {
            card8.setY(0);
        } else {
            card8.setY(-20);
        }
        selectedCards[7] = !selectedCards[7];
    }

    public void card9Clicked() {
        if (selectedCards[8]) {
            card9.setY(0);
        } else {
            card9.setY(-20);
        }
        selectedCards[8] = !selectedCards[8];
    }

    public void card10Clicked() {
        if (selectedCards[9]) {
            card10.setY(0);
        } else {
            card10.setY(-20);
        }
        selectedCards[9] = !selectedCards[9];
    }

    public void card11Clicked() {
        if (selectedCards[10]) {
            card11.setY(0);
        } else {
            card11.setY(-20);
        }
        selectedCards[10] = !selectedCards[10];
    }

    public void card12Clicked() {
        if (selectedCards[11]) {
            card12.setY(0);
        } else {
            card12.setY(-20);
        }
        selectedCards[11] = !selectedCards[11];
    }

    public void card13Clicked() {
        if (selectedCards[12]) {
            card13.setY(0);
        } else {
            card13.setY(-20);
        }
        selectedCards[12] = !selectedCards[12];
    }

    public void card14Clicked() {
        if (selectedCards[13]) {
            card14.setY(0);
        } else {
            card14.setY(-20);
        }
        selectedCards[13] = !selectedCards[13];
    }

    public void card15Clicked() {
        if (selectedCards[14]) {
            card15.setY(0);
        } else {
            card15.setY(-20);
        }
        selectedCards[14] = !selectedCards[14];
    }

    public void card16Clicked() {
        if (selectedCards[15]) {
            card16.setY(0);
        } else {
            card16.setY(-20);
        }
        selectedCards[15] = !selectedCards[15];
    }

    public void card17Clicked() {
        if (selectedCards[16]) {
            card17.setY(0);
        } else {
            card17.setY(-20);
        }
        selectedCards[16] = !selectedCards[16];
    }

    public void card18Clicked() {
        if (selectedCards[17]) {
            card18.setY(0);
        } else {
            card18.setY(-20);
        }
        selectedCards[17] = !selectedCards[17];
    }

    public void card19Clicked() {
        if (selectedCards[18]) {
            card19.setY(0);
        } else {
            card19.setY(-20);
        }
        selectedCards[18] = !selectedCards[18];
    }

    public void card20Clicked() {
        if (selectedCards[19]) {
            card20.setY(0);
        } else {
            card20.setY(-20);
        }
        selectedCards[19] = !selectedCards[19];
    }

    public void onConfirmClicked() {
        if (receiveThread != null) {
            if (receiveThread.getGameState() == 2) {
                sendMessage("DOUBLE@true");
                hideButtons();
            } else if (receiveThread.getGameState() == 0) {
                sendMessage("READY");
                hideButtons();
            } else {
                Vector<Card> discards = new Vector<>();
                int startPos = (20 - Integer.parseInt(remaining1.getText())) / 2;
                for (int i = 0; i < 20; i++) {
                    if (selectedCards[i]) {
                        discards.add(receiveThread.getCardsList().get(i - startPos));
                    }
                }
                if (judge.judgeSelf(discards)) {
                    StringBuilder sb = new StringBuilder("DISCARD");
                    for (Card card : discards) {
                        sb.append("@");
                        sb.append(card.content());
                    }
                    sendMessage(sb.toString());
                    resetCardSelect();
                    hideButtons();
                } else {
                    showAlert("您的牌型不正确！");
                }
            }
        }
    }

    public void onPassClicked() {
        if (receiveThread.getGameState() == 1) {
            sendMessage("CALL@0");
        } else if (receiveThread.getGameState() == 2) {
            sendMessage("DOUBLE@false");
        } else {
            resetCardSelect();
            sendMessage("PASS");
        }
        hideButtons();
    }

    public void onCall3Clicked() {
        sendMessage("CALL@3");
        hideButtons();
    }

    public void onCall2Clicked() {
        sendMessage("CALL@2");
        hideButtons();
    }

    public void onCall1Clicked() {
        sendMessage("CALL@1");
        hideButtons();
    }

    public void onConnectClick() {
        if ("".equals(name.getText())) {
            showAlert("昵称不能为空！");
            return;
        }
        if (name.getText().contains(" ")) {
            showAlert("昵称不能包含空格字符！");
            return;
        }
        if (name.getText().contains("@")) {
            showAlert("昵称不能包含“@”！");
            return;
        }
        if (name.getText().length() > 16) {
            showAlert("昵称长度不能超过16个字符！");
            return;
        }
        try {
            socket = new Socket(hostname.getText(), Integer.parseInt(port.getText()));
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            writer = new PrintWriter(socket.getOutputStream());
            sendMessage(name.getText() + "@" + pwd.getText());
            String message = reader.readLine();
            if ("MAX".equals(message)) {
                showAlert("房间已满！");
                socket.close();
            } else if ("SAME".equals(message)) {
                showAlert("昵称已被使用！");
                socket.close();
            } else if ("WRONG".equals(message)) {
                showAlert("密码错误");
                socket.close();
            } else {
                UIHelper uiHelper = new UIHelper(this);
                mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE);
                mediaPlayer.play();
                chatHistory.clear();
                chatHistory.appendText("[服务器]连接成功！\n");
                String[] split = message.split("@");
                StringBuilder sb = new StringBuilder("[服务器]局数：");
                sb.append(split[1]);
                sb.append(" 记牌器：");
                if ("true".equals(split[2])) {
                    tips.setVisible(true);
                    sb.append("有");
                } else {
                    tips.setVisible(false);
                    sb.append("无");
                }
                sb.append(" 加倍：");
                if ("true".equals(split[3])) {
                    sb.append("允许");
                } else {
                    sb.append("禁止");
                }
                sb.append(" 交流：");
                if ("true".equals(split[4])) {
                    send.setDisable(false);
                    sb.append("允许");
                } else {
                    sb.append("禁止");
                }
                sb.append('\n');
                chatHistory.appendText(sb.toString());
                rounds.setText("0/" + split[1]);
                info1.setText("");
                info2.setText("");
                info3.setText("");
                if ("false".equals(split[5])) {
                    confirm.setText("准备");
                    confirm.setVisible(true);
                }
                judge = new Judge();
                receiveThread = new ReceiveThread(this, socket, name.getText(), judge, uiHelper);
                receiveThread.setDaemon(true);
                receiveThread.start();
                connect.setDisable(true);
                disconnect.setDisable(false);
                hostname.setDisable(true);
                port.setDisable(true);
                pwd.setDisable(true);
                name.setDisable(true);
            }
        } catch (NumberFormatException e) {
            showAlert("端口号格式错误!");
        } catch (IllegalArgumentException e) {
            showAlert("端口号超出范围!");
        } catch (IOException e) {
            e.printStackTrace();
            showAlert("无法连接至服务器！\n请检查输入的主机和端口是否正确!");
        }
    }

    public void onDisconnectClick() throws IOException {
        if (socket != null) {
            sendMessage("CLOSE");
            socket.close();
        }
        mediaPlayer.stop();
        chatHistory.appendText("[服务器]已断开连接！\n");
        connect.setDisable(false);
        disconnect.setDisable(true);
        hostname.setDisable(false);
        port.setDisable(false);
        pwd.setDisable(false);
        name.setDisable(false);
        send.setDisable(true);
        confirm.setVisible(false);
        pass.setVisible(false);
        call1.setVisible(false);
        call2.setVisible(false);
        call3.setVisible(false);
        rounds.setText("");
        landlordCard.setText("");
        points.setText("");
        tips.setVisible(false);
        UIHelper uiHelper1 = new UIHelper(this);
        uiHelper1.resetAll();
    }

    public void onOpenServerClick() throws IOException {
        FXMLLoader loader = new FXMLLoader(DDZApplication.class.getResource("server-view.fxml"));
        VBox root = loader.load();
        Scene scene = new Scene(root);
        ServerController serverController = loader.getController();
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.setResizable(false);
        stage.setTitle("简单斗地主服务端");
        stage.getIcons().add(new Image(Main.class.getResource("icon.png").openStream()));
        stage.show();
        stage.setOnCloseRequest(windowEvent -> serverController.onStopButtonClick());
    }

    public void onSendClick() {
        String str = chat.getText().replaceAll("\n", "");
        if (!"".equals(str)) {
            sendMessage("CHAT@" + str);
            chat.clear();
        }
    }

    private void showAlert(String s) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setHeaderText(s);
        alert.showAndWait();
    }

    private void resetCardSelect() {
        selectedCards = new boolean[20];
        card1.setY(0);
        card2.setY(0);
        card3.setY(0);
        card4.setY(0);
        card5.setY(0);
        card6.setY(0);
        card7.setY(0);
        card8.setY(0);
        card9.setY(0);
        card10.setY(0);
        card11.setY(0);
        card12.setY(0);
        card13.setY(0);
        card14.setY(0);
        card15.setY(0);
        card16.setY(0);
        card17.setY(0);
        card18.setY(0);
        card19.setY(0);
        card20.setY(0);
    }

    private void hideButtons() {
        call1.setVisible(false);
        call2.setVisible(false);
        call3.setVisible(false);
        pass.setVisible(false);
        confirm.setVisible(false);
    }

    private void sendMessage(String s) {
        writer.println(s);
        writer.flush();
    }

    public void handleKeyPressedSend(KeyEvent keyEvent) {
        String str = chat.getText().replaceAll("\n", "");
        if (keyEvent.getCode().equals(KeyCode.ENTER)) {
            if (!"".equals(str) && writer != null && !send.isDisable()) {
                sendMessage("CHAT@" + str);
            }
            chat.clear();
        }
    }

    public void stopBGM() {
        mediaPlayer.stop();
    }
}
